/**
 * DOM工具函数
 */

/**
 * 获取元素
 * @param {string|Element} selector - 选择器或元素
 * @returns {Element|null} 元素
 */
export function $(selector) {
  if (typeof selector === 'string') {
    return document.querySelector(selector);
  }
  return selector;
}

/**
 * 获取所有元素
 * @param {string} selector - 选择器
 * @returns {NodeList} 元素列表
 */
export function $$(selector) {
  return document.querySelectorAll(selector);
}

/**
 * 添加类名
 * @param {Element} element - 元素
 * @param {string} className - 类名
 */
export function addClass(element, className) {
  if (element && element.classList) {
    element.classList.add(className);
  }
}

/**
 * 移除类名
 * @param {Element} element - 元素
 * @param {string} className - 类名
 */
export function removeClass(element, className) {
  if (element && element.classList) {
    element.classList.remove(className);
  }
}

/**
 * 切换类名
 * @param {Element} element - 元素
 * @param {string} className - 类名
 * @returns {boolean} 是否包含类名
 */
export function toggleClass(element, className) {
  if (element && element.classList) {
    return element.classList.toggle(className);
  }
  return false;
}

/**
 * 检查是否包含类名
 * @param {Element} element - 元素
 * @param {string} className - 类名
 * @returns {boolean} 是否包含类名
 */
export function hasClass(element, className) {
  if (element && element.classList) {
    return element.classList.contains(className);
  }
  return false;
}

/**
 * 设置样式
 * @param {Element} element - 元素
 * @param {string|Object} property - 样式属性或样式对象
 * @param {string} value - 样式值
 */
export function setStyle(element, property, value) {
  if (!element) {
    return;
  }

  if (typeof property === 'object') {
    Object.assign(element.style, property);
  } else {
    element.style[property] = value;
  }
}

/**
 * 获取样式
 * @param {Element} element - 元素
 * @param {string} property - 样式属性
 * @returns {string} 样式值
 */
export function getStyle(element, property) {
  if (!element) {
    return '';
  }
  return window.getComputedStyle(element)[property];
}

/**
 * 获取元素位置
 * @param {Element} element - 元素
 * @returns {Object} 位置信息
 */
export function getOffset(element) {
  if (!element) {
    return { top: 0, left: 0, width: 0, height: 0 };
  }

  const rect = element.getBoundingClientRect();
  return {
    top: rect.top + window.pageYOffset,
    left: rect.left + window.pageXOffset,
    width: rect.width,
    height: rect.height,
  };
}

/**
 * 滚动到元素
 * @param {Element|string} element - 元素或选择器
 * @param {Object} options - 选项
 */
export function scrollTo(element, options = {}) {
  const el = typeof element === 'string' ? $(element) : element;
  if (!el) {
    return;
  }

  const { behavior = 'smooth', block = 'start', inline = 'nearest' } = options;

  el.scrollIntoView({ behavior, block, inline });
}

/**
 * 防抖函数
 * @param {Function} func - 函数
 * @param {number} delay - 延迟时间
 * @returns {Function} 防抖后的函数
 */
export function debounce(func, delay) {
  let timeoutId;
  return function (...args) {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func.apply(this, args), delay);
  };
}

/**
 * 节流函数
 * @param {Function} func - 函数
 * @param {number} delay - 延迟时间
 * @returns {Function} 节流后的函数
 */
export function throttle(func, delay) {
  let lastCall = 0;
  return function (...args) {
    const now = Date.now();
    if (now - lastCall >= delay) {
      lastCall = now;
      func.apply(this, args);
    }
  };
}

/**
 * 事件监听器
 * @param {Element} element - 元素
 * @param {string} event - 事件名
 * @param {Function} handler - 处理函数
 * @param {Object} options - 选项
 */
export function on(element, event, handler, options = {}) {
  if (!element) {
    return;
  }
  element.addEventListener(event, handler, options);
}

/**
 * 移除事件监听器
 * @param {Element} element - 元素
 * @param {string} event - 事件名
 * @param {Function} handler - 处理函数
 * @param {Object} options - 选项
 */
export function off(element, event, handler, options = {}) {
  if (!element) {
    return;
  }
  element.removeEventListener(event, handler, options);
}

/**
 * 一次性事件监听器
 * @param {Element} element - 元素
 * @param {string} event - 事件名
 * @param {Function} handler - 处理函数
 * @param {Object} options - 选项
 */
export function once(element, event, handler, options = {}) {
  if (!element) {
    return;
  }
  const onceHandler = function (...args) {
    handler.apply(this, args);
    off(element, event, onceHandler, options);
  };
  on(element, event, onceHandler, options);
}

/**
 * 触发事件
 * @param {Element} element - 元素
 * @param {string} event - 事件名
 * @param {any} detail - 事件详情
 */
export function trigger(element, event, detail = null) {
  if (!element) {
    return;
  }

  const customEvent = new CustomEvent(event, {
    detail,
    bubbles: true,
    cancelable: true,
  });

  element.dispatchEvent(customEvent);
}

/**
 * 检查元素是否在视口中
 * @param {Element} element - 元素
 * @param {number} threshold - 阈值
 * @returns {boolean} 是否在视口中
 */
export function isInViewport(element, threshold = 0) {
  if (!element) {
    return false;
  }

  const rect = element.getBoundingClientRect();
  const windowHeight =
    window.innerHeight || document.documentElement.clientHeight;
  const windowWidth = window.innerWidth || document.documentElement.clientWidth;

  return (
    rect.top >= -threshold &&
    rect.left >= -threshold &&
    rect.bottom <= windowHeight + threshold &&
    rect.right <= windowWidth + threshold
  );
}

/**
 * 获取元素的所有父元素
 * @param {Element} element - 元素
 * @returns {Array} 父元素数组
 */
export function getParents(element) {
  const parents = [];
  let parent = element.parentElement;

  while (parent) {
    parents.push(parent);
    parent = parent.parentElement;
  }

  return parents;
}

/**
 * 查找最近的匹配元素
 * @param {Element} element - 元素
 * @param {string} selector - 选择器
 * @returns {Element|null} 匹配的元素
 */
export function closest(element, selector) {
  if (!element) {
    return null;
  }

  if (element.matches && element.matches(selector)) {
    return element;
  }

  return closest(element.parentElement, selector);
}
